import * as THREE from 'three'
import { KongZhi } from './KongZhi.js'
import { sheZhi } from '../cunChu/bianLiang.js'
import { huanJing } from '../huanJing/HuanJing.js'
import { wanJia } from '../changJing/wuTi/WanJia.js'
import { YueShu } from '../changJing/yueShu/YueShu.js'
import { JiaoLian } from '../changJing/yueShu/JiaoLian.js'
import { HuaKuai } from '../changJing/yueShu/HuaKuai.js'
import { gengXinJiHe } from '../gengXin/gengXin.js'
import { jieMian } from '../jieMian/zuJian/JieMian.js'

// 制造模式

let moRenKuaiJieJian = {
	xuanZhongMuBiao: {
		miaoShu: '选中目标',
		xiangQing: '选中目标',
		kuaiJieJian: 'Digit1'
	},
	quXiaoMuBiao: {
		miaoShu: '取消目标',
		xiangQing: '取消目标',
		kuaiJieJian: 'Digit2'
	},
	tianJiaGuDing: {
		miaoShu: '添加固定',
		xiangQing: '给选中的两个物体添加固定约束（两个物体中，第一个选中的物体作为参考物体，决定正方向）',
		kuaiJieJian: 'Digit3'
	},
	tianJiaJiaoLian: {
		miaoShu: '添加铰链',
		xiangQing: '给选中的两个物体添加铰链约束（两个物体中，第一个选中的物体作为参考物体，决定正方向）',
		kuaiJieJian: 'Digit4'
	},
	tianJiaHuaKuai: {
		miaoShu: '添加滑块',
		xiangQing: '给选中的两个物体添加滑块约束（两个物体中，第一个选中的物体作为参考物体，决定正方向）',
		kuaiJieJian: 'Digit5'
	},
	jiaYueShuFanWei: {
		miaoShu: '加约束范围/shift减范围',
		xiangQing: '给选中的约束增加约束范围，同时按住shift减少范围',
		kuaiJieJian: 'Digit6'
	},
	xuanZhuanYueShuX: {
		miaoShu: '旋转约束红轴/shift反向',
		xiangQing: '选中的约束绕红轴旋转，同时按住shift反向旋转',
		kuaiJieJian: 'Digit7'
	},
	xuanZhuanYueShuY: {
		miaoShu: '旋转约束绿轴/shift反向',
		xiangQing: '选中的约束绕绿轴旋转，同时按住shift反向旋转',
		kuaiJieJian: 'Digit8'
	},
	xuanZhuanYueShuZ: {
		miaoShu: '旋转约束蓝轴/shift反向',
		xiangQing: '选中的约束绕蓝轴旋转，同时按住shift反向旋转',
		kuaiJieJian: 'Digit9'
	},
	shiQu: {
		miaoShu: '拾取',
		xiangQing: '准星对准物体，按住按键进行拾取后，可移动物体',
		kuaiJieJian: 'KeyR'
	},
	shanChuYueShu: {
		miaoShu: '删除约束',
		xiangQing: '删除选中的约束',
		kuaiJieJian: 'KeyX'
	}
}

Object.defineProperty(moRenKuaiJieJian, 'miaoShu', {
	value: '制造模式',
	enumerable: false
})

let zhiZaoMoShi = null

class ZhiZaoMoShi extends KongZhi {
	kuaiJieJianBianHao = 'ZhiZaoMoShi'
	kuaiJieJian = null
	shiQuZhuangTai = false // 拾取状态
	shiQuDian = null // 拾取点
	muBiao = null // 拾取的物体或约束
	dianYueShu = null // 拾取点的约束
	yueShuWuTi = new Set() // 要约束的两个物体
	bianHuanYueShu = null // 变换的约束
	
	constructor() {
		super()
		
		if (sheZhi.kuaiJieJian[this.kuaiJieJianBianHao]) this.kuaiJieJian = sheZhi.kuaiJieJian[this.kuaiJieJianBianHao] // 从存储中加载快捷键
		else this.kuaiJieJian = sheZhi.kuaiJieJian[this.kuaiJieJianBianHao] = moRenKuaiJieJian
		// 拾取点
		let dianCaiZhi = shengChengDianCaiZhi()
		this.shiQuDian = new THREE.Mesh( new THREE.SphereGeometry( 0.05, 16, 8 ), dianCaiZhi )
		this.shiQuDian.layers.enable(huanJing.houQiChuLi.BLOOM_SCENE)
		
		zhiZaoMoShi = this
	}
	
	chuLi(shiJian) {
		if (shiJian.type == 'keydown') this.keydown(shiJian)
		if (shiJian.type == 'keyup') this.keyup(shiJian)
	}
	
	keydown(shiJian) {
		let kjj = this.kuaiJieJian
		let shiftKey = shiJian.shiftKey

		switch (shiJian.code) {
			case kjj.xuanZhongMuBiao.kuaiJieJian:
				this.xuanZhongMuBiao()
				break;
			case kjj.quXiaoMuBiao.kuaiJieJian:
				this.quXiaoMuBiao(this.muBiao)
				break;
			case kjj.tianJiaGuDing.kuaiJieJian:
				this.tianJiaGuDing()
				break;
			case kjj.tianJiaJiaoLian.kuaiJieJian:
				this.tianJiaJiaoLian()
				break;
			case kjj.tianJiaHuaKuai.kuaiJieJian:
				this.tianJiaHuaKuai()
				break;
			case kjj.xuanZhuanYueShuX.kuaiJieJian:
				this.xuanZhuanYueShu('X', shiftKey)
				break;
			case kjj.xuanZhuanYueShuY.kuaiJieJian:
				this.xuanZhuanYueShu('Y', shiftKey)
				break;
			case kjj.xuanZhuanYueShuZ.kuaiJieJian:
				this.xuanZhuanYueShu('Z', shiftKey)
				break;
			case kjj.jiaYueShuFanWei.kuaiJieJian:
				this.jiaYueShuFanWei(shiftKey)
				break;
			case kjj.shiQu.kuaiJieJian:
				this.shiQu()
				break;
			case kjj.shanChuYueShu.kuaiJieJian:
				this.shanChuYueShu()
				break;
		}
	}
	
	keyup(shiJian) {
		let kjj = this.kuaiJieJian
	
		switch (shiJian.code) {
			case kjj.shiQu.kuaiJieJian:
				this.fangXia()
				break;
		}
	}
	// 切换目标
	qieHuanMuBiao() {
		if (this.shiQuZhuangTai) return
		
		let { scene, camera, houQiChuLi } = huanJing
		let { xiangJiFuZhu } = wanJia
		let shi = xiangJiFuZhu.getWorldPosition(new THREE.Vector3())
		let chaoXiang = xiangJiFuZhu.getWorldDirection (new THREE.Vector3()).negate() // 因为xiangJiFuZhu旋转了180度，取反才是玩家面向
		
		let juLi = 10
		let raycaster = new THREE.Raycaster(shi, chaoXiang, 0, juLi)
		raycaster.camera = camera
	
		let jianCeMoXing = []

		huanJing.scene.traverseVisible(a => {
			let muBiao = a.userData.huoQuYueShu?.() ?? a.userData.huoQuWuTi?.()
			if (muBiao) {
				if (muBiao.shiHengXing || muBiao.shiXingXing) return

				if (a.isMesh && !a.isSprite && !a.isInstancedMesh) jianCeMoXing.push(a)
			}
		})

		let xiangJiao = raycaster.intersectObjects(jianCeMoXing, false)

		if (xiangJiao.length > 0) {
			let yueShu = xiangJiao.find(a => a.object.userData.huoQuYueShu)
			let xj = yueShu || xiangJiao[0]
			let { object, point } = xj
			let weiZhi = point.clone()
			
			wanJia.xiangJiFuZhu.worldToLocal(weiZhi)
			this.shiQuDian.position.copy(weiZhi)
			wanJia.xiangJiFuZhu.add(this.shiQuDian)

			this.muBiao = object.userData.huoQuYueShu?.() ?? object.userData.huoQuWuTi?.()

			houQiChuLi.bianKuang.selectedObjects = [this.muBiao.moXing]
		} else {
			houQiChuLi.bianKuang.selectedObjects = []
			
			this.shiQuDian.removeFromParent()
			
			this.muBiao = null
		}
	}
	// 拾取
	shiQu() {
		if (!this.muBiao) return
		if (this.shiQuZhuangTai) return
		
		if (this.muBiao.shiGangTi) {
			// 不能拾取比玩家质量大的物体
			if (this.muBiao.zhiLiang > wanJia.zhiLiang) return
			
			let shiJieZuoBiao = this.shiQuDian.getWorldPosition(new THREE.Vector3())
			let weiZhiA = this.muBiao.moXing.worldToLocal(shiJieZuoBiao)
			this.muBiao.sheZhiPengZhuangTi({ jiaoZuLi: 1 })
			this.dianYueShu = new YueShu('点', { wuTiA: this.muBiao, weiZhiA })
			this.dianYueShu.jiaZai()
		}
		
		this.shiQuZhuangTai = true
	}
	// 放下
	fangXia() {
		if (!this.muBiao) return
		if (!this.shiQuZhuangTai) return

		if (this.muBiao.shiGangTi) {
			this.muBiao.sheZhiPengZhuangTi({ jiaoZuLi: 0 })
		}
		
		this.dianYueShu?.xieZai()
		this.dianYueShu = null
		this.shiQuZhuangTai = false
	}
	// 移动目标
	yiDongMuBiao() {
		if (!this.shiQuZhuangTai) return
		
		let shiJieWeiZhi = this.shiQuDian.getWorldPosition(new THREE.Vector3())
		
		// 设置刚体目标约束点位置
		if (this.muBiao.shiGangTi) {
			this.dianYueShu.sheZhiYueShu({ dian: { weiZhiB: shiJieWeiZhi } })
		}
		// 设置约束目标模型位置
		if (this.muBiao.shiYueShu) {
			if (this.muBiao.jiaZaiZhuangTai) return
			
			let benDiZuoBiao = this.muBiao.moXing.parent.worldToLocal(shiJieWeiZhi.clone())
			this.muBiao.moXing.position.copy(benDiZuoBiao)
		}
	}
	// 高亮显示切换
	gaoLiang(muBiao, shiFou) {
		let cengJi = huanJing.houQiChuLi.BLOOM_SCENE
		let shuXing = shiFou ? 'enable' : 'disable'

		if (muBiao.shiGangTi) {
			muBiao.moXing.traverseVisible(a => {
				if (a.userData.huoQuWuTi && a.userData.huoQuWuTi() == muBiao) a.layers[shuXing](cengJi)
			})
		} else if (muBiao.shiYueShu) {
			muBiao.moXing.traverseVisible(a => {
				if (a.userData.huoQuYueShu && a.userData.huoQuYueShu() == muBiao) a.layers[shuXing](cengJi)
			})
		} else {
			muBiao.traverse(a => a.layers[shuXing](cengJi))
		}
	}
	// 选中约束物体或要变换的约束
	xuanZhongMuBiao() {
		let muBiao = this.muBiao
		
		if (muBiao) {
			if (muBiao.shiGangTi) {
				if (this.yueShuWuTi.has(muBiao)) {
					let shuZu = [...this.yueShuWuTi]
					if (shuZu[0] == muBiao && shuZu.length == 2) {
						[shuZu[1], shuZu[0]] = [shuZu[0], shuZu[1]]
						this.yueShuWuTi = new Set(shuZu)
					}
				} else {
					this.gaoLiang(muBiao, true)
					this.yueShuWuTi.add(muBiao)
				}

				if (this.yueShuWuTi.size == 3) this.quXiaoMuBiao([...this.yueShuWuTi][0])
			}

			if (muBiao != this.bianHuanYueShu) {
				if (this.bianHuanYueShu) {
					this.gaoLiang(this.bianHuanYueShu, false)
					this.bianHuanYueShu = null
				}
				if (muBiao.shiYueShu) {
					this.gaoLiang(muBiao, true)
					this.bianHuanYueShu = muBiao
				}
			}
		}
	}
	// 取消选中约束物体或要变换的约束
	quXiaoMuBiao(muBiao) {
		let yueShuWuTi = this.yueShuWuTi
		
		if (muBiao) {
			if (muBiao?.shiGangTi && yueShuWuTi.has(muBiao)) yueShuWuTi.delete(muBiao)

			if (muBiao.shiYueShu) this.bianHuanYueShu = null

			this.gaoLiang(muBiao, false)
		}
	}
	// 清空选中的约束物体或约束
	qingKongMuBiao() {
		this.yueShuWuTi.forEach(a => this.gaoLiang(a, false))
		this.yueShuWuTi.clear()

		if (this.bianHuanYueShu) this.gaoLiang(this.bianHuanYueShu, false)
		this.bianHuanYueShu = null
	}
	// 添加固定
	tianJiaGuDing() {
		if (!this.muBiao) return

		let yueShuWuTi = this.yueShuWuTi

		if (yueShuWuTi.size === 2) {
			let wuTi = yueShuWuTi.keys()
			let wuTiA = wuTi.next().value
			let wuTiB = wuTi.next().value
			
			let weiZhi = this.shiQuDian.getWorldPosition(new THREE.Vector3())
			let weiZhiA = wuTiA.moXing.worldToLocal(weiZhi.clone())
			let weiZhiB = wuTiB.moXing.worldToLocal(weiZhi)
			
			let yueShu = new YueShu('固定', { wuTiA, wuTiB, weiZhiA, weiZhiB })
			yueShu.moXing.visible = true
			yueShu.jiaZai()
			
			this.qingKongMuBiao()
		}
	}
	// 添加铰链
	tianJiaJiaoLian() {
		if (!this.muBiao) return

		let yueShuWuTi = this.yueShuWuTi
		if (yueShuWuTi.size === 2) {
			let wuTi = yueShuWuTi.keys()
			let wuTiA = wuTi.next().value
			let wuTiB = wuTi.next().value
			
			let weiZhi = this.shiQuDian.getWorldPosition(new THREE.Vector3())
			let weiZhiA = wuTiA.moXing.worldToLocal(weiZhi.clone())
			let weiZhiB = wuTiB.moXing.worldToLocal(weiZhi)
	
			let yueShu = new JiaoLian(wuTiA, wuTiB, weiZhiA, weiZhiB)
			yueShu.moXing.visible = true
			yueShu.jiaZai()
			
			this.qingKongMuBiao()
		}
	}
	// 添加滑块
	tianJiaHuaKuai() {
		if (!this.muBiao) return

		let yueShuWuTi = this.yueShuWuTi
		if (yueShuWuTi.size === 2) {
			let wuTi = yueShuWuTi.keys()
			let wuTiA = wuTi.next().value
			let wuTiB = wuTi.next().value
			
			let weiZhi = this.shiQuDian.getWorldPosition(new THREE.Vector3())
			let weiZhiA = wuTiA.moXing.worldToLocal(weiZhi.clone())
			let weiZhiB = wuTiB.moXing.worldToLocal(weiZhi)
	
			let yueShu = new HuaKuai(wuTiA, wuTiB, weiZhiA, weiZhiB)
			yueShu.moXing.visible = true
			yueShu.jiaZai()
			
			this.qingKongMuBiao()
		}
	}
	// 旋转约束
	xuanZhuanYueShu(zhou, shiftKey = false) {
		let bianHuanYueShu = this.bianHuanYueShu
		if (bianHuanYueShu) {
			let huDu = Math.PI / 180
			let fuHao = shiftKey ? -1 : 1
			bianHuanYueShu.moXing[`rotate${zhou}`](huDu * fuHao)
			
			bianHuanYueShu.gengXinYueShuCanShu()
			bianHuanYueShu.xieZai()
			bianHuanYueShu.jiaZai()
		}
	}
	// 约束加范围
	jiaYueShuFanWei(shiftKey = false) {
		let bianHuanYueShu = this.bianHuanYueShu

		if (bianHuanYueShu && bianHuanYueShu.yueShuFanWei) {
			let zuiXiao = 0, zuiDa = 0
			let liang = 0 // 每次增减量
			let yueShuFanWei = bianHuanYueShu.yueShuFanWei
			
			if (bianHuanYueShu.yueShuLeiXing == '铰链') {
				zuiXiao = 0
				zuiDa = Math.PI * 1.999
				liang = Math.PI / 180
			}
			if (bianHuanYueShu.yueShuLeiXing == '滑块') {
				zuiXiao = 0
				zuiDa = 10
				liang = 0.1
			}
			
			if (shiftKey) yueShuFanWei.zuiDa = Math.max(zuiXiao, yueShuFanWei.zuiDa - liang)
			else yueShuFanWei.zuiDa = Math.min(zuiDa, yueShuFanWei.zuiDa + liang)
			
			bianHuanYueShu.gengXinJiHeTi(bianHuanYueShu.moXing)
		}
	}
	// 删除约束
	shanChuYueShu() {
		if (this.bianHuanYueShu) {
			this.bianHuanYueShu.xiaoHui()
			this.bianHuanYueShu = null
		}
	}
	// 显示约束模型
	xianShiYueShu(xianShi) {
		for (let i = 0, l = YueShu.quanBuYueShu.length; i < l; i++) {
			let yueShu = YueShu.quanBuYueShu[i]
			if (!yueShu.shiKongZhiTi) yueShu.moXing.visible = xianShi
		}
	}
	// 打开界面
	daKaiJieMian() {
		// 生成技能条
		let jiNengTiao = jieMian.jiNengTiao
		jiNengTiao.shadowRoot.innerHTML = ''
		
		for(let i in this.kuaiJieJian) {
			let jiNeng = this.kuaiJieJian[i]
			jiNengTiao.shengChengJiNeng(jiNeng)
		}
		// 准星
		jieMian.zhunXing.style.setProperty('display', 'block')
	}
	// 关闭界面
	guanBiJieMian() {
		//  删除技能条
		let jiNengTiao = jieMian.jiNengTiao
		jiNengTiao.shadowRoot.innerHTML = ''
		jieMian.zhunXing.style.setProperty('display', 'none')
	}
	
	gengXin() {
		this.qieHuanMuBiao()
		this.yiDongMuBiao()
	}
	
	jiaZai() {
		super.jiaZai()
		this.xianShiYueShu(true)
		this.daKaiJieMian()
		gengXinJiHe.set(this, this.gengXin.bind(this))
	}
	
	xieZai() {
		super.xieZai()
		this.qingKongMuBiao()
		this.xianShiYueShu(false)
		huanJing.houQiChuLi.bianKuang.selectedObjects = []
		this.shiQuDian.removeFromParent()
		this.muBiao = null
		this.guanBiJieMian()
		gengXinJiHe.delete(this)
	}
}

function shengChengDianCaiZhi() {
	let shaderMaterial = new THREE.ShaderMaterial({
		vertexShader: `
			#include <common>
			${THREE.ShaderChunk.logdepthbuf_pars_vertex}
			varying vec2 vUv;
			void main() {
				vUv = uv;
				gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
				${THREE.ShaderChunk.logdepthbuf_vertex}
			}
		`,
		fragmentShader: `
			#include <common>
			${THREE.ShaderChunk.logdepthbuf_pars_fragment}
			uniform float gradient;
			varying vec2 vUv;
			void main() {
				float color = smoothstep(0.0, gradient, vUv.y); // 使用smoothstep函数产生渐变效果
				gl_FragColor = vec4(vec3((color + 0.2) * 0.3, (color + 0.2) * 0.7, 1.0), 1.0);
				${THREE.ShaderChunk.logdepthbuf_fragment}
			}
		`,
		uniforms: {
			gradient: { value: 1.0 } ,// 定义渐变颜色的强度，范围是0到1
		}
	});

	return shaderMaterial
}

export {
	ZhiZaoMoShi,
	zhiZaoMoShi
};